package com.my.chapter21;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class practice22 {
    public static void main(String[] args) throws Exception {
        BusyWait.main(args);
        System.out.println("--------------------------");
        WaitNotify.main(args);
    }
}

class BusyWait{
    private static volatile boolean flag;
    private static int spins;

    public static void main(String[] args) throws InterruptedException {
        Runnable r1 = new Runnable() {
            public void run() {
                for(;;) {
                    try {
                        TimeUnit.MILLISECONDS.sleep(10);
                    } catch (InterruptedException e) { return; }
                    flag = true;
                }
            }
        };
        Runnable r2 = new Runnable() {
            public void run() {
                for(;;) {
                    // The busy-wait loop
                    while(!flag &&
                            !Thread.currentThread().isInterrupted())
                        spins++;
                    System.out.println("Spun " + spins + " times");
                    spins = 0;
                    flag = false;
                    if(Thread.interrupted())
                        return;
                }
            }
        };
        ExecutorService exec = Executors.newCachedThreadPool();
        exec.execute(r1);
        exec.execute(r2);
        TimeUnit.SECONDS.sleep(1);
        exec.shutdownNow();
    }
}

/*r2任务在r1上调用wait（），在r1本身上调用notify（）。
同样，这个程序的“正确性”取决于r1的睡眠时间；
如果注释掉相应的行，则会由于信号丢失而死锁。*/

class WaitNotify{
    public static void main(String[] args) throws Exception {
        final Runnable r1 = new Runnable() {
            public void run() {
                for(;;) {
                    try {
                        TimeUnit.MILLISECONDS.sleep(100);
                        synchronized(this) { notify(); }
                    } catch(InterruptedException e) { return; }
                }
            }
        };
        Runnable r2 = new Runnable() {
            public void run() {
                for(;;) {
                    try {
                        synchronized(r1) { r1.wait(); }
                    } catch(InterruptedException e) { return; }
                    System.out.print("Cycled ");
                }
            }
        };
        ExecutorService exec = Executors.newCachedThreadPool();
        exec.execute(r1);
        exec.execute(r2);
        TimeUnit.SECONDS.sleep(1);
        exec.shutdownNow();
    }
}
